using System;
using System.Collections.Generic;
using System.Text;

using System.Management.Automation;

namespace Microsoft.PowerShell.CmdletManagement
{
    [Cmdlet(VerbsCommon.New, "PsSpecNoun", SupportsShouldProcess = true)]
    public class NewPsSpecNounCommand : Cmdlet
    {
        [Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
        [ValidateLength(1, 50)]
        public String Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
            }
        }
        private string _name = "*";

        [Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
        [ValidateLength(1, 2000)]
        public String Definition
        {
            get
            {
                return _definition;
            }
            set
            {
                _definition = value;
            }
        }
        private string _definition = "*";

        [Parameter(Mandatory = true, Position = 2, ValueFromPipelineByPropertyName = true)]
        [ValidateLength(1, 50)]
        public String ProjectName
        {
            get
            {
                return _project;
            }
            set
            {
                _project = value;
            }
        }
        private string _project = "";

        [Parameter(Mandatory = false)]
        public String ServiceUri
        {
            get
            {
                return _serviceUri;
            }
            set
            {
                _serviceUri = value;
            }
        }
        private string _serviceUri = PsSpecCmdletUtils.Constants.ServiceUri;


        protected override void ProcessRecord()
        {
            // Check that they've specified a valid name
            if (! PsSpecCmdletUtils.IsValidWildcardedNounName(Name))
            {
                WriteError(new ErrorRecord(
                    new Exception(resources.InvalidNounName),
                    "INVALID_NOUN_NAME", 
                    ErrorCategory.InvalidArgument, Name));
                return;
            }

            // Fail if the noun exists
            if (NounExists(Name, ServiceUri))
            {
                WriteError(new ErrorRecord(
                    new Exception(resources.NounAlreadyExists),
                    "INVALID_NOUN_NAME",
                    ErrorCategory.InvalidArgument, Name));
                return;
            }

            if (ShouldProcess(
                String.Format("{0}", ServiceUri),
                String.Format(resources.CreateNounShouldProcess, Name)))
            {
                PsSpecCmdletService.CmdletService service =
                    new PsSpecCmdletService.CmdletService();
                service.Url = ServiceUri;
                
                service.UseDefaultCredentials = true;

                try
                {
                    service.NewNoun(Name, Definition, ProjectName);

                    // Retrieve the noun to output
                    GetPsSpecNounCommand psSpecNounCommand = new GetPsSpecNounCommand();
                    psSpecNounCommand.Name = Name;
                    psSpecNounCommand.Definition = Definition;
                    psSpecNounCommand.ProjectName = ProjectName;
                    psSpecNounCommand.ServiceUri = ServiceUri;

                    WriteObject(psSpecNounCommand.Invoke(), true);
                }
                catch (System.Web.Services.Protocols.SoapException e)
                {
                    WriteError(new ErrorRecord(e, "CMDLET_SERVICE_ERROR", ErrorCategory.InvalidOperation, Name));
                }
            }
        }

        private bool NounExists(string name, string serviceUri)
        {
            GetPsSpecNounCommand psSpecNounCommand = new GetPsSpecNounCommand();
            psSpecNounCommand.Name = name;
            psSpecNounCommand.Quiet = true;
            psSpecNounCommand.ServiceUri = serviceUri;

            bool nounFound = false;
            foreach(bool result in psSpecNounCommand.Invoke())
            {
                nounFound = result;
            }
            
            return nounFound;
        }
    }
}
